package com.wiegand.sound {
	import com.caurina.transitions.Tweener;
	import com.wiegand.loader.SoundLoader;

	import flash.events.EventDispatcher;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundTransform;

	/**
	 * @author kwiegand
	 */
	 
	public class Soundcontroller extends EventDispatcher {

		private static var _instance : Soundcontroller;	
			
		private var _bgSoundChannel : SoundChannel;		
		private var _bgTransform : SoundTransform;	
		
		private var _effSoundChannel : SoundChannel;		
		private var _effTransform : SoundTransform;	
					
		private var _playing : Boolean = true;		
		
		private var _soundBt : ISoundButton;
		
		private const TIME_FADE_IN : Number = 3;
		private const TIME_FADE_OUT : Number = 1;
		
		private const MAX_BG_VOLUME : Number = 0.7;
		private const MAX_EFF_VOLUME : Number = 0.8;

		private var _curentVolum : Number = 1;
		
		public static var EVENT_START_LOADING : String = "start sound loading";
		public static var EVENT_LOADING_COMPLETE : String = "sound loading complete";

		public static function getInstance() : Soundcontroller{
			
			if( _instance == null )
				_instance = new Soundcontroller( new SingletonEnforecer() );
			
			return _instance;
			
		}
		
		public function Soundcontroller( blocker:SingletonEnforecer ):void{
			if ( blocker == null ) {
            	throw new Error("Error: Instantiation failed: Use Soundcontroller.getInstance() instead of new.");
          	}
          	else{
          		init();
          	}
		}
		
		private function init():void{
			_bgTransform = new SoundTransform();	
			_bgTransform.volume = MAX_BG_VOLUME;
			
			_bgSoundChannel = new SoundChannel();
			_bgSoundChannel.soundTransform = _bgTransform;
		
			_effTransform = new SoundTransform();	
			_effTransform.volume = MAX_EFF_VOLUME;
			
			_effSoundChannel = new SoundChannel();
			_effSoundChannel.soundTransform = _effTransform;
		}

		public function playBgSound( soundName : String = "" ) : void {
			if( soundName == "" ){
				_bgSoundChannel.soundTransform = _bgTransform;
			}
			else{
				var sound : Sound = SoundLoader.getInstance().getSound( soundName );			
				fadeoutBgSound( sound );
			}
		}

		public function muteBgSound() : void {
			 var transform : SoundTransform = new SoundTransform();
			 transform.volume = 0;
			_bgSoundChannel.soundTransform = transform;		
		}
		
		private function fadeinBgSound() : void {	
			if( _playing ){
				var newBgVol : Number = (_curentVolum * MAX_BG_VOLUME);				
				Tweener.addTween( _bgTransform, { volume:newBgVol, time:TIME_FADE_IN, transition:"linear", onUpdate: updateBgChannel });
			}
		}
		
		private function fadeoutBgSound( sound : Sound = null ) : void {
			if( _playing ){
				Tweener.addTween( _bgTransform, { volume:0, time:TIME_FADE_OUT, transition:"linear", onUpdate: updateBgChannel, onComplete:changeBgSound, onCompleteParams: [ sound ] });
			}
			else{
				changeBgSound( sound );
			}
		}
		
		private function changeBgSound( sound : Sound ) : void {
			if(sound != null){
				_bgSoundChannel.stop();
				_bgSoundChannel = sound.play( 0, int.MAX_VALUE );
				_bgSoundChannel.soundTransform = _bgTransform;
				fadeinBgSound();
			}
		}
		
		private function updateBgChannel() : void{
			_bgSoundChannel.soundTransform = _bgTransform;
		}
		
		public function playEffSound( soundName : String ) : void {
			if( _playing && soundName != null){
				var sound : Sound = SoundLoader.getInstance().getSound( soundName );
				_effSoundChannel.stop();
				_effSoundChannel = sound.play( 0, 1 );	
				_effSoundChannel.soundTransform = _effTransform;		
			}
		}
		
		private function turnVolumeOn() :void{
			_playing = true;
			Tweener.addTween( _bgTransform, { volume:_curentVolum, time:TIME_FADE_IN, transition:"linear", onUpdate: updateBgChannel });
		}
		
		private function turnVolumeOff() :void{
			_playing = false;
			Tweener.addTween( _bgTransform, { volume:0, time:TIME_FADE_OUT, transition:"linear", onUpdate: updateBgChannel });
		}
		
		public function toggleVolume( s : String = "default" ) :void{
			switch( s ){
				
				case "default"	: 	if( _playing ) turnVolumeOff();
									else turnVolumeOn();
									break;
				case "on"		:	turnVolumeOn();
									break;
				case "off"		:	turnVolumeOff();
									break;
				default			:	break;
			}
		}
		public function toggleBgVolume( s : String = "default" ) :void{
			switch( s ){
				
				case "default"	: 	if( _bgTransform.volume > 0 ) fadeoutBgSound();
									else fadeinBgSound();
									break;
				case "on"		:	fadeinBgSound();
									break;
				case "off"		:	fadeoutBgSound();
									break;
				default			:	break;
			}
		}
		
		public function updateVolume(volume:Number):void{	
			_curentVolum = volume;
					
			var newBgVol : Number = (volume*MAX_BG_VOLUME);
			_bgTransform.volume = newBgVol;
			_bgSoundChannel.soundTransform = _bgTransform;
			
			var newEffVol : Number = (volume*MAX_EFF_VOLUME);
			_effTransform.volume = newEffVol;
			_effSoundChannel.soundTransform = _effTransform;
		}
		
		public function get volume():Number{
			return _bgTransform.volume;
		}
		
		public function set soundBt(bt:ISoundButton):void{
			_soundBt = bt;
		}
		
	}
}

internal class SingletonEnforecer {}
